#coding=utf-8
#
# Copyright (C) 2014  NianNian TECH Co., Ltd. All rights reserved.
# Created on Jul 25, 2014, by Junn
#

from core.views import CustomAPIView
from core.decorators import login_required_pro, login_required_mtd
from regards.forms import RegardForm, TipForm
from utils import http, logs, eggs
from utils.http import Response
from regards.models import Regard, DateTip, NewRegardMessage, SystemMsg
from regards.serializers import RegardSerializer, PagingRegardSerializer
from core.serializers import serialize_response
import regards
import settings
import datetime
from users.models import User
from core import codes
from rest_framework.decorators import api_view
from django.db import transaction
from utils.eggs import handle_paging

class RegardSendAction(CustomAPIView):
    '''发送问候: 可从亲友列表或直接从通讯录选择联系人.
        
        分支情况: 
        1. 若亲友未注册: 自动为其注册, 发送"咚咚问候", 并短信提示        ----****
        2. 当用户已注册(在当前家庭/在其他家庭/无家庭): 直接发送咚咚问候
    '''
    
    @login_required_pro
    @transaction.commit_manually  # 采用事务, 处理回复问候失败的情况
    def post(self, req):
        
        rid = req.REQUEST.get('rid') #regard receiver_id(问候接收人)
        phone = req.REQUEST.get('phone')
        nickname = req.REQUEST.get('name', '')
        if not rid and not phone: 
            return http.failed('No any params passed, need rid or phone ')
        
        if rid: #rid优先
            receiver = User.objects.get_cached(int(rid))
            if not receiver:
                return http.resp('object_not_found', 'rid:%s' % rid)
        else:
            if not eggs.is_phone_valid(phone):
                return http.failed('手机号格式不正确')
            receiver = User.objects.get_by_phone(eggs.normalize_phone(phone))
        
        sms_content = ''
        
        #用户未注册时, 操作步骤: 注册用户, 添加到当前家庭, 发送咚咚问候, 发送短信
        if not receiver: 
            current_family = req.user.get_family
            if not current_family:
                return http.failed('还没有任何家庭, 无法添加成员: %s' % req.user.id)
            #if current_family.is_members_full(): return http.failed('成员数已达最大值, 新联系人无法添加')
            
            phone = eggs.normalize_phone(phone)
            password = eggs.random_num()
            receiver = User.objects._create_user(phone, password, phone=phone, 
                                                 nickname=nickname, acct_type='I', is_active=False)
            #current_family.add_member(receiver)
            sms_content = settings.REGARD_SMS.format(phone, password)
        
        regard_form = RegardForm(req.user, receiver, req.POST, req.FILES)
        if not regard_form.is_valid():
            logs.error('参数错误: %s' % regard_form.errors)
            return http.failed('参数错误')
        
        try:
            regard = regard_form.save()
        except Exception, e:
            logs.error('Create regard error \n %s' % e)
            return http.failed()  
        
        reply_to = req.REQUEST.get('reply_to')  # 被回复的问候id
        if reply_to:
            success, cause = regard.reply(reply_to)
            if not success:
                try:
                    transaction.rollback()      #回复失败则回滚数据
                except Exception, e: 
                    logs.error('transaction.rollback error: \n %s' % e)
                return http.failed('回复问候失败')
        
        transaction.commit()
            
        return Response(codes.append('ok', {'data': RegardSerializer(regard).data, 
                                            'sms_content': sms_content}))

class RegardsAction(CustomAPIView):
    '''兼容: 咚咚1.5.0及之前的版本, 保留该接口'''

    @login_required_pro
    def post(self, req):
        return eggs.NotImplResponse()

    @login_required_pro
    def get(self, req):
        '''返回用户发送或接收到的问候列表 
        @param last_item_time: 上次请求最后一条数据的发送时间
        @param rtype: R-接收到的问候, S-发送的问候
        @param sender: 问候发送者id(user_id). 该参数为空时, 返回所有发送者发送的给当前用户的问候数据
        '''
        last_item_time = req.REQUEST.get('last_item_time')
        limit_count = req.REQUEST.get('limit_count', 10)
        
        rtype = req.REQUEST.get('rtype', 'R')
        sender = req.REQUEST.get('sender', 0)
        if rtype == 'S': #发送的问候
            regards = Regard.objects.get_sent(req.user, last_item_time)
        else:   #收到的问候
            regards = Regard.objects.get_received(req.user, last_item_time, sender=int(sender))
            NewRegardMessage.objects.clear_message_count(receiver_id=req.user.id, sender_id=int(sender))

        items = handle_paging(req, regards)
        return Response(PagingRegardSerializer(instance=items, results_field_name='regards').data)        
    
class RegardsReceivedList(CustomAPIView):
    '''收到的问候列表'''
    
    @login_required_pro
    def get(self, req):
        '''用户收到的问候
        @param last_item_time: 上次请求最后一条数据的发送时间
        @param sender: 问候发送者id(user_id). 该参数为空时, 返回所有发送者发送的问候数据
        '''
        last_item_time = req.REQUEST.get('last_item_time')
        sender = req.REQUEST.get('sender', 0)
        regards = Regard.objects.get_received(req.user, last_item_time, sender=int(sender))
        NewRegardMessage.objects.clear_message_count(receiver_id=req.user.id, sender_id=int(sender))
        return serialize_response(list(regards))
    
class RegardsSentList(CustomAPIView):
    '''获取用户发送的问候列表'''
     
    @login_required_pro
    def get(self, req):
        last_item_time = req.REQUEST.get('last_item_time')
        regards = Regard.objects.get_sent(req.user, last_item_time)
        
        # 临时处理1.8.1版本"我发的问候"Bug: reply_by<>{}显示数据错误, TODO:后期删除
        for r in regards:
            if r.reply_by:
                r.reply_by = None
        
        return serialize_response(list(regards))        

class RegardCheckView(CustomAPIView):  
    
    def put(self, req, rid):              
        '''设置问候为已读'''
        try:
            regard = Regard.objects.get(id=int(rid))
            if not regard.is_checked:
                regard.check()
                regard.save()
            return http.ok()
        except Regard.DoesNotExist:
            return http.failed() 
 

class RegardView(CustomAPIView):
    
    def get(self, req, rid):
        '''获取问候详情'''
        try:
            regard = Regard.objects.get(id=int(rid))
            return serialize_response(regard)
        except Regard.DoesNotExist:
            logs.error('Regard %s not found ' % rid)
            return http.object_not_found()
    
    def put(self, req, rid):
        '''目前仅支持功能: 重设待发送问候发送时间'''
        
        sent_time = req.DATA.get('sent_time', None)
        
        try:
            regard = Regard.objects.get(id=int(rid))
            if regard.is_sent():
                return http.failed('已发送的问候无法重设时间')
            
            if not sent_time: #立即发送
                regard.is_sent_now = True
                regard.sent_time = datetime.datetime.now()
                regard.send()
            else:
                regard.sent_time = sent_time
                
            regard.save()
            return serialize_response(regard)
        except Regard.DoesNotExist:
            logs.error('Regard %s not found ' % rid)
            return http.object_not_found()

    def delete(self, req, rid):
        '''撤销某条待发送问候'''
        try:
            regard = Regard.objects.get(id=int(rid))
            if regard.is_sent():
                return http.failed('已发送问候不能撤销')
            
            regard.delete()
            return http.ok()
        except Regard.DoesNotExist:
            logs.error('Regard %s not found ' % rid)
            return http.object_not_found()
            

class TipsAction(CustomAPIView):
    
    @login_required_pro
    def post(self, req):
        '''添加或修改事件提醒. 
        当tid不空时, 修改已有提醒. 否则新添加提醒
        '''
        
        tid = req.POST.get('tid', '')
        form = TipForm(req.user, tid, req.POST)
        if form.is_valid():
            tip = form.save()
            return serialize_response(tip)
        logs.error(form.errors)
        return http.failed('参数格式错误')
    
    @login_required_pro       
    def get(self, req):
        '''获取登录用户的提醒列表'''
        last_time = req.REQUEST.get('last_item_time')
        limit_count = req.REQUEST.get('limit_count')
        NewRegardMessage.objects.clear_message_count(receiver_id=req.user.id, msg_type='T')
        tips = DateTip.objects.get_by_user(req.user, last_time, limit_count=limit_count)
        if not tips:
            return Response([])
            
        return serialize_response(list(tips)) #app_name='regards'
    
    def put(self, req, tid):
        '''修改事件提醒'''
        return eggs.NotImplResponse()
    
    @login_required_pro       
    def delete(self, req, tid):
        '''删除提醒'''
        try:
            tip = DateTip.objects.get(id=int(tid))
            if req.user != tip.creator:
                return http.resp('permission_denied')
            tip.delete()
            return http.ok()
        except Exception, e:
            logs.error('Delete datetip error: %s' % e)
            return http.failed('%s' % e)
        
@api_view(['POST'])
@login_required_mtd
def check_datetip(req, tid):  
    '''查看并处理事件提醒, 将is_checked标识置为True 
    '''
    try: 
        date_tip = DateTip.objects.get(id=int(tid))
        if req.user != date_tip.creator:
            return http.resp('permission_denied')
        
        if date_tip.is_triggered:        #仅对已触发的提醒进行check操作
            date_tip.is_checked = True
            date_tip.save()
    except Exception, e:
        logs.err(__name__, eggs.lineno(), e)
        return http.failed('操作异常')
    
    return http.ok()
        
@api_view(['GET'])
@login_required_mtd
def pull_new_messages(req):
    '''主用于咚咚(消息)界面, 拉取消息. 需要登录用户
    若msg.count=0, 则表示历史消息, 否则为新消息
    '''
    
    user = req.user
    last_item_time = req.REQUEST.get('last_item_time')
    data = []
    msgs = NewRegardMessage.objects.get_many(user, last_time=last_item_time)
    for msg in msgs:
        sender = User.objects.get_cached(msg.sender)
        rs = {
            'sender': sender.id, 'sender_avatar': sender.avatar, 
            'sender_nickname': sender.nickname, 'msg_count': msg.count, 
            'msg_type': msg.msg_type, 'item_content': msg.item_content, 
            'item_time': str(msg.item_time)
        }
        
        # 用户已读的系统消息, 将msg_count置0, 以此保持系统消息已读状态
        if rs['msg_type'] == 'S' and req.session.get('sys_msg_received'):
            rs['msg_count'] = 0
            req.session['sys_msg_received'] = False
        
        data.append(rs)

    # 消息被拉取后, 将新消息设置为"已推送", 且将pushed_err_count 清0. 拉取操作相当于"已推送"
    if not last_item_time:
        NewRegardMessage.objects.set_pushed(user)
    
    return Response(codes.append('ok', {'data': data, 'total_count': NewRegardMessage.objects.count_new(user)}))        


@api_view(['GET'])
#@login_required_mtd
def get_system_messages(req):
    '''获取当前用户的系统消息'''
    
    last_item_time = req.REQUEST.get('last_item_time')
    user = req.user if req.user.is_authenticated() else None
    msgs = SystemMsg.objects.get_received(user=user, last_time=last_item_time)
    NewRegardMessage.objects.clear_message_count(sender_id=settings.SYS_ADMIN, msg_type='S')
    
    # 使用该标识, 以判定用户是否已读取系统消息
    req.session['sys_msg_received'] = True
    
    return serialize_response(list(msgs))
    

# def start_regards_sending_thread(req, action):
#     if action not in ('start', 'stop'): 
#         return http.failed('unknown action: %s' % action) 
#     
#     sending_thread = settings.RS_THREAD
#     if action == 'start':
#         if not sending_thread or not sending_thread.is_started():
#             sending_thread = RegardSendingThread(name='regard_sending_thread')
#             sending_thread.start()
#             settings.RS_THREAD = sending_thread
#         else:    
#             return http.ok({'thread has been started, dont need to start again': 0})
#     else: # stop
#         if sending_thread and sending_thread.is_started():
#             sending_thread.stop()  
#             return http.ok({'thread stoped': 0})
#         else:
#             return http.failed('''sending_thread is None, or can't stop the thread which not started''' )    
#             
#     return http.ok({'thread started:': sending_thread.getName()}) 
        
        
        
        
        

